﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace ProjectNocturnalFool
{
    /// <summary>
    /// A static class consisting of a Vector2 called Location
    /// </summary>
    static class Camera
    {
        #region Fields
        
        public static int viewHeight;
        public static int viewWidth;
        
        private static int _worldWidth;
        public static int worldWidth {
            get {return (int)(_worldWidth*scale);}
            set {_worldWidth=value;}
        }
        private static int _worldHeight;
        public static int worldHeight {
            get { return (int)(_worldHeight*scale);}
            set{_worldHeight=value;}
        }

        public static Vector2 displayOffset { get; set; }

        private static float scaleIndex;
        public static float scale { get { return scaleIndex * Constants.camScaleIncrement; } set { scaleIndex = value / Constants.camScaleIncrement; } }

        static public Vector2 location;
        public static Vector2 Location{
            get{ return location;}
            set{ location = new Vector2(MathHelper.Clamp(value.X, 0f, worldWidth - viewWidth), MathHelper.Clamp(value.Y, 0f, worldHeight - viewHeight));}
        }



        //private static Vector2 _camShakeVel;
        //public static Vector2 camShakeVel{
        //    get { return _camShakeVel; }
        //    set {
        //        if (value.Length() <= Constants.camShakeVelMax) { _camShakeVel = value; }
        //        else { _camShakeVel = Vector2.Normalize(value)*(Constants.camShakeVelMax); }
        //    }
        //}

        public static Velocity camShakeVelocity;
        public static int camShakeTimer=0;
        //public static Vector2 camShakeAcc;
        public static bool camShaking;


        #endregion


        #region Methods

        public static Vector2 WorldToScreen(Vector2 worldPosition)
        {
            return (worldPosition) - location + displayOffset;
        }

        public static Vector2 ScreenToWorld(Vector2 screenPosition)
        {
            return  location - displayOffset +(screenPosition );
        }

        public static void Move(Vector2 offset)
        {
            Location += offset;
        }

        public static Vector2 getCentre() {
            return new Vector2(location.X + (viewWidth / 2), location.Y + (viewHeight / 2));
        }

        public static void zoomIn()
        {
            float oldScale = scale;
            scaleIndex++;
            scaleIndex = MathHelper.Clamp(scaleIndex, Constants.camMinScale / Constants.camScaleIncrement, Constants.camMaxScale / Constants.camScaleIncrement);
            Vector2 newCenter = new Vector2(getCentre().X * scale / oldScale, getCentre().Y * scale / oldScale);
            Location = newCenter - new Vector2(viewWidth / 2, viewHeight / 2);
            
        }

        public static void zoomOut()
        {
            float oldScale = scale;
            scaleIndex --;
            scaleIndex = MathHelper.Clamp(scaleIndex, Constants.camMinScale / Constants.camScaleIncrement, Constants.camMaxScale / Constants.camScaleIncrement);
            Vector2 newCenter = new Vector2(getCentre().X * scale/oldScale, getCentre().Y * scale/oldScale);
            Location = newCenter - new Vector2(viewWidth / 2, viewHeight / 2);
        }

        public static void startShake() {
            camShaking = true;
            camShakeVelocity = new Velocity(new Vector2(0, 0), new Vector2(0, 100), 0.1f);
            camShakeTimer=0;
        }

        public static void stopShake()
        {
            camShaking = false;
            //camShakeAcc = Vector2.Zero;
            //camShakeVel = Vector2.Zero;
            displayOffset = Vector2.Zero;
        }
        #endregion

        #region Init and Update

        /// <summary>
        /// Must be run prior to usage of Camera
        /// </summary>
        public static void Init() {
            location = Vector2.Zero;
            displayOffset = Vector2.Zero; 
            scaleIndex = Constants.camDefaultScaleIndex;
                        
            //_camShakeVel = Vector2.Zero;
            //camShakeAcc = Vector2.Zero;
            
        }

        public static void Update() {
            if(camShaking){
                //camShake();
            }
            
        }

        #endregion

        #region Private Helper Methods
        private static void camShake() {
            //camShakeVel += camShakeAcc;
            //displayOffset += camShakeVel;
            //Vector2 oldV = camShakeVelocity.currentVelocity;
            camShakeVelocity.Update();
            displayOffset = camShakeVelocity.currentVelocity;
            if (camShakeTimer%30==15 && camShakeVelocity.targetVelocity.Length()>10) {
                camShakeVelocity = new Velocity(camShakeVelocity.currentVelocity, -1 * (camShakeVelocity.currentVelocity - (10)*Vector2.Normalize(camShakeVelocity.currentVelocity)), 0.1f);
            }
            else if (camShakeVelocity.targetVelocity.Length() <= 10) {
                camShakeVelocity.currentVelocity = Vector2.Zero;
                camShakeVelocity.targetVelocity = Vector2.Zero;
                stopShake();
            }
            camShakeTimer++;
        }

        #endregion
    }
}
